package com.xy.smartsms.db.carrierparam;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.xy.smartsms.db.base.MixCursor;
import com.xy.smartsms.db.carrierparam.entity.BlackListDb;
import com.xy.smartsms.db.carrierparam.entity.OnlineConfigDb;
import com.xy.smartsms.db.carrierparam.entity.WhiteListDb;
import com.xy.smartsms.util.Log;

import java.io.BufferedReader;
import java.util.Hashtable;

import cn.com.xy.sms.sdk.util.FileUtils;

/**
 * Created by kangwenbo on 2017/3/17.
 */

public class CarrierDBManager {
    private static String TAG = CarrierDBManager.class.getSimpleName();
    private static final String dataBaseName = "carrierparam.db";
    static final int dataBaseVersion = 1;
    static MyDbHelper dbHelper = null;
    static int timeOut = 1000;
    static int sleepTime = 100;
    public static Object dblock = new Object();
    static Hashtable<SQLiteDatabase, Integer> listDB = new Hashtable<SQLiteDatabase, Integer>();

    private static SQLiteDatabase createSQLiteDatabase(Context contexts) {

        synchronized (listDB) {
            if (listDB.size() >= 10) {
                return null;
            }
            MyDbHelper helper = getHelper(contexts.getApplicationContext());
            SQLiteDatabase db = helper.getReadableDatabase();
            Integer cnt = null;
            if (db != null) {
                cnt = listDB.get(db);
                if (cnt == null) {
                    cnt = 1;
                } else {
                    cnt++;
                }
                listDB.put(db, cnt);
                if (!db.isOpen()) {
                    Log.d(TAG, "is not open.");
                    listDB.remove(db);
                    return null;
                }
            }
            return db;
        }
    }

    public synchronized static void close(SQLiteDatabase db) {
        try {
            if (db == null) {
                Log.d(TAG, " db close is null");
                return;
            }
            synchronized (listDB) {
                Integer cnt = listDB.get(db);
                if (cnt == null) {
                    Log.d(TAG, " db close cnt is null "+ db.hashCode());
                    // 这种情况如果发生就是有问题的
                    // db.close();
                } else {
                    cnt = cnt - 1;
                    if (cnt == 0) {
                        listDB.remove(db);
                        db.close();
                        // cnt);
                    } else {
                        listDB.put(db, cnt);
                    }
                }
            }
            if (listDB.size() == 0) {
                Log.d(TAG, "db close listDB size is 0");
                if (dbHelper != null) {
                    dbHelper.close();
                }
                // System.gc();
            }
        } catch (Throwable e) {
            Log.d(TAG, "CarrierDBManager close " + e.getMessage());
        }

    }

    public synchronized static SQLiteDatabase getSQLiteDatabase(Context context) {
        SQLiteDatabase sb = null;
        long start = System.currentTimeMillis();
        long end = 0;
        while (sb == null) {

            sb = createSQLiteDatabase(context);
            if (sb != null) {
                return sb;
            }
            end = System.currentTimeMillis();
            end = (end - start);
            if (end >= timeOut) {
                break;
            }
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                Log.e(TAG, "CarrierDBManager getSQLiteDatabase ", e);
            }
        }
        return sb;
    }

    private synchronized static MyDbHelper getHelper(Context contexts) {

        if (dbHelper == null) {
            dbHelper = new MyDbHelper(contexts, dataBaseName, null,
                    dataBaseVersion);
        }
        return dbHelper;
    }

    private static class MyDbHelper extends SQLiteOpenHelper {
        public MyDbHelper(Context contexts, String name, SQLiteDatabase.CursorFactory factory,
                          int version) {
            super(contexts, name, factory, version);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

            try {
                createDb(db);
            } catch (Throwable e) {
                Log.e(TAG, "onCreate: ", e);
            }
        }

        @Override
        public void onOpen(SQLiteDatabase db) {
            super.onOpen(db);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            createDb(db);
        }

        @Override
        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            createDb(db);
        }
    }

    private static void createDb(SQLiteDatabase SQLiteDatabase) {
        try {
            SQLiteDatabase.execSQL(WhiteListDb.CREATE_TABLE);
            SQLiteDatabase.execSQL(BlackListDb.CREATE_TABLE);
            SQLiteDatabase.execSQL(OnlineConfigDb.CREATE_TABLE);

        } catch (Throwable e) {
            Log.e(TAG, "createDb: ", e);
        }

    }

    private static void addColumn(SQLiteDatabase SQLiteDatabase, String sql) {
        try {
            SQLiteDatabase.execSQL(sql);
        } catch (Throwable e) {
        }
    }

    private static SQLiteDatabase getReadSQLiteDatabase(Context context) {
        return getSQLiteDatabase(context);
    }

    public static MixCursor query(Context context, String tableName, String[] columns,
                                  String selection, String[] selectionArgs) throws Exception {
        return query(context, false, tableName, columns, selection, selectionArgs, null,
                null, null, null);
    }

    public static MixCursor query(Context context, boolean distinct, String tableName,
                                  String[] columns, String selection, String[] selectionArgs,
                                  String groupBy, String having, String orderBy, String limit)
            throws Exception {

        MixCursor mixCursor = null;
        SQLiteDatabase mySQLiteDatabase = null;
        try {
            mySQLiteDatabase = getReadSQLiteDatabase(context);
            Cursor cursor = mySQLiteDatabase.query(distinct, tableName,
                    columns, selection, selectionArgs, groupBy, having,
                    orderBy, limit);
            mixCursor = new MixCursor(mySQLiteDatabase, cursor, 4);
        } catch (Throwable e) {
            close(mySQLiteDatabase);
        }
        return mixCursor;
    }

    public static MixCursor query(Context context, String tableName, String[] columns,
                                  String selection, String[] selectionArgs, String groupBy,
                                  String having, String orderBy, String limit) throws Exception {
        // initDbManager();
        MixCursor mixCursor = null;
        SQLiteDatabase mySQLiteDatabase = null;
        try {
            mySQLiteDatabase = getSQLiteDatabase(context);
            Cursor cursor = mySQLiteDatabase.query(tableName, columns,
                    selection, selectionArgs, groupBy, having, orderBy, limit);
            mixCursor = new MixCursor(mySQLiteDatabase, cursor, 4);
        } catch (Throwable e) {
            close(mySQLiteDatabase);
            Log.e(TAG, "CarrierDBManager 1query ", e);
        } finally {

        }
        return mixCursor;
    }

    public static int delete(Context context, String tableName, String whereClause,
                             String[] whereArgs) throws Exception {
        // initDbManager();

        synchronized (dblock) {
            int res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase(context);
                res = mySQLiteDatabase
                        .delete(tableName, whereClause, whereArgs);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static int update(Context context, String tableName, ContentValues values,
                             String whereClause, String[] whereArgs) throws Exception {
        synchronized (dblock) {
            int res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase(context);
                res = mySQLiteDatabase.update(tableName, values, whereClause,
                        whereArgs);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static long insert(Context context, String tableName, ContentValues values)
            throws Exception {
        synchronized (dblock) {
            long res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase(context);
                res = mySQLiteDatabase.insert(tableName, null, values);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static MixCursor rawQuery(Context context, String sql, String[] selectionArgs)
            throws Exception {
        // initDbManager();
        SQLiteDatabase mySQLiteDatabase = null;
        MixCursor mixCursor = null;

        try {
            mySQLiteDatabase = getSQLiteDatabase(context);
            Cursor cursor = mySQLiteDatabase.rawQuery(sql, selectionArgs);
            mixCursor = new MixCursor(mySQLiteDatabase, cursor, 4);
        } catch (Throwable e) {
            close(mySQLiteDatabase);
            Log.e(TAG, "CarrierDBManager rawQuery ", e);
        }
        return mixCursor;
    }


    public static void closeDB(String filePath, boolean isDeleteFile,
                               java.io.LineNumberReader r, BufferedReader bw, SQLiteDatabase db) {
        try {
            try {
                if (isDeleteFile) {
                    FileUtils.deleteAllFile(filePath);
                }
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            try {
                if (r != null)
                    r.close();
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            try {
                if (bw != null)
                    bw.close();
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            if (db != null) {
                try {
                    if (db.inTransaction()) {
                        db.setTransactionSuccessful();
                        db.endTransaction();
                    }
                } catch (Throwable e) {
                    Log.e(TAG, "closeDB: ", e);
                } finally {
                    close(db);
                }
            }
        } catch (Throwable e) {
            Log.e(TAG, "CarrierDBManager closeDB ", e);
        }
    }

    public static void closeCursor(Cursor cur) {
        if (cur != null) {
            cur.close();
        }
    }

}
